/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @addtogroup Surface
 * @{
 *
 * @brief Provides the capabilities of applying for and releasing shared memory in multimedia and graphics scenarios.
 *
 * @since 1.0
 * @version 1.0
 */

/**
 * @file surface.h
 *
 * @brief Provides the capabilities of applying for and releasing shared memory in multimedia and graphics scenarios.
 *
 * By default, a surface can apply for a shared buffer. You can call {@link SetQueueSize} to set the maximum number
 * of buffers that can be applied for. \n
 *
 * @since 1.0
 * @version 1.0
 */

#ifndef GRAPHIC_LITE_SURFACE_H
#define GRAPHIC_LITE_SURFACE_H

#include "ibuffer_consumer_listener.h"
#include "surface_buffer.h"
#include "surface_type.h"

namespace OHOS {
/**
 * @brief Defines the consumer listener used to notify consumers when the surface status is updated.
 *
 * @since 1.0
 * @version 1.0
 */
class Surface {
public:
    /**
     * @brief A constructor used to create a {@link Surface} object for consumers to use.
     *
     * In multi-process scenarios, this function is provided for consumers to obtain buffers generated by producers
     * for consumption. \n
     * In single-process scenarios, this function can be used by both consumers and producers. \n
     *
     * @since 1.0
     * @version 1.0
     */
    static Surface* CreateSurface();

    /**
     * @brief A destructor used to delete the <b>Surface</b> instance.
     *
     * This function releases the surface and all buffers applied for the surface.
     *
     * @since 1.0
     * @version 1.0
     */
    virtual ~Surface();

    /**
     * @brief Sets the number of buffers that can be allocated to the surface.
     * The default value is <b>1</b>. The value range is [1, 10].
     *
     * @param queueSize Indicates the number of buffers to set.
     * @since 1.0
     * @version 1.0
     */
    virtual void SetQueueSize(uint8_t queueSize) = 0;

    /**
     * @brief Obtains the number of surface buffers that can be allocated to the surface.
     * The default value is <b>1</b>. The value range is [1, 10].
     *
     * @return Returns the number of buffers.
     * @since 1.0
     * @version 1.0
     */
    virtual uint8_t GetQueueSize() = 0;

    /**
     * @brief Sets the width and height of the surface for calculating its stride and size.
     * The default value range of width and height is (0,7680].
     *
     * @param width Indicates the surface width, in pixels.
     * @param height Indicates the surface height, in pixels.
     * @since 1.0
     * @version 1.0
     */
    virtual void SetWidthAndHeight(uint32_t width, uint32_t height) = 0;

    /**
     * @brief Obtains the width of the surface.
     *
     * @return Returns the surface width, in pixels.
     * @since 1.0
     * @version 1.0 */
    virtual uint32_t GetWidth() = 0;

    /**
     * @brief Obtains the height of the surface.
     *
     * @return Returns the surface height, in pixels.
     * @since 1.0
     * @version 1.0
     */
    virtual uint32_t GetHeight() = 0;

    /**
     * @brief Sets the pixel format of the surface. For details, see {@link ImageFormat}.
     * The default pixel format is {@link IMAGE_PIXEL_FORMAT_RGB565}.
     *
     *
     * @param format Indicates the pixel format to be set.
     * @since 1.0
     * @version 1.0
     */
    virtual void SetFormat(uint32_t format) = 0;

    /**
     * @brief Obtains the pixel format of the surface. For details, see {@link ImageFormat}.
     * The default pixel format is {@link IMAGE_PIXEL_FORMAT_RGB565}.
     *
     * @return Returns the pixel format.
     * @since 1.0
     * @version 1.0
     */
    virtual uint32_t GetFormat() = 0;

    /**
     * @brief Sets the number of bytes for stride alignment.
     *
     * By default, 4-byte aligned is used. The value range is [4,32].
     *
     * @param strideAlignment Indicates the number of bytes for stride alignment.
     * @since 1.0
     * @version 1.0
     */
    virtual void SetStrideAlignment(uint32_t strideAlignment) = 0;

    /**
     * @brief Obtains the number of bytes for stride alignment. By default, 4-byte aligned is used.
     *
     * @return Returns the number of bytes for stride alignment.
     * @since 1.0
     * @version 1.0
     */
    virtual uint32_t GetStrideAlignment() = 0;

    /**
     * @brief Obtains the stride of the surface.
     *
     * @return Returns the stride.
     * @since 1.0
     * @version 1.0
     */
    virtual uint32_t GetStride() = 0;

    /**
     * @brief Sets the size of the shared memory to allocate.
     *
     *
     * @param size Indicates the size of the shared memory. The value range is (0,58982400].
     * @since 1.0
     * @version 1.0
     */
    virtual void SetSize(uint32_t size) = 0;

    /**
     * @brief Obtains the size of the shared memory to allocate.
     *
     * @return Returns the size of the shared memory.
     * @since 1.0
     * @version 1.0
     */
    virtual uint32_t GetSize() = 0;

    /**
     * @brief Sets the usage scenario of the buffer. Physically contiguous memory and virtual memory (by default)
     * are supported. By default, virtual memory is allocated.
     *
     * @param usage Indicates the usage scenario of the buffer. For details, see {@link BUFFER_CONSUMER_USAGE}.
     * @since 1.0
     * @version 1.0
     */
    virtual void SetUsage(uint32_t usage) = 0;

    /**
     * @brief Obtains the usage scenario of the buffer. Physically contiguous memory and virtual memory are supported.
     *
     * @return Returns the usage scenario of the buffer. For details, see {@link BUFFER_CONSUMER_USAGE}.
     * @since 1.0
     * @version 1.0
     */
    virtual uint32_t GetUsage() = 0;

    /**
     * @brief Sets surface user data, which is stored in the format of <key, value>.
     *
     * @param key Indicates the key of a key-value pair to store.
     * @param value Indicates the value of the key-value pair to store.
     * @since 1.0
     * @version 1.0
     */
    virtual void SetUserData(const std::string& key, const std::string& value) = 0;

    /**
     * @brief Obtains surface user data.
     *
     * @param key Indicates the key of a key-value pair for which the value is to be obtained.
     * @return Returns the value of the key-value pair obtained.
     * @since 1.0
     * @version 1.0
     */
    virtual std::string GetUserData(const std::string& key) = 0;

    /**
     * @brief Obtains a buffer to write data.
     *
     *
     * @param wait Specifies whether the function waits for an available buffer. If <b>wait</b> is <b>1</b>,
     * the function waits until there is an available buffer in the free queue before returning a pointer.
     * If the <b>wait</b> is <b>0</b>, the function does not wait and returns <b>nullptr</b> if there is no buffer
     * in the free queue. The default value is <b>0</b>.
     * @return Returns the pointer to the buffer if the operation is successful; returns <b>nullptr</b> otherwise.
     * @since 1.0
     * @version 1.0
     */
    virtual SurfaceBuffer* RequestBuffer(uint8_t wait = 0) = 0;

    /**
     * @brief Flushes a buffer to the dirty queue for consumers to use.
     *
     *
     *
     * @param SurfaceBuffer Indicates the pointer to the buffer flushed by producers.
     * @return Returns <b>0</b> if the operation is successful; returns <b>-1</b> otherwise.
     * @since 1.0
     * @version 1.0
     */
    virtual int32_t FlushBuffer(SurfaceBuffer* buffer) = 0;

    /**
     * @brief Obtains a buffer.
     *
     * Consumers can use this function to obtain the buffer placed in the dirty queue by producers.
     * If there is no buffer in the queue, <b>nullptr</b> is returned.
     *
     * @return Returns the pointer to the {@link SurfaceBuffer} object.
     * @since 1.0
     * @version 1.0
     */
    virtual SurfaceBuffer* AcquireBuffer() = 0;

    /**
     * @brief Releases the consumed buffer.
     *
     * After a consumer has used a {@link SurfaceBuffer} object, the consumer can release it through
     * {@link ReleaseBuffer}. The released object is placed into the free queue so that producers can
     * apply for the object.
     *
     * @param SurfaceBuffer Indicates the pointer to the buffer released.
     * @return Returns <b>true</b> if the buffer is released; returns <b>false</b> otherwise.
     * @since 1.0
     * @version 1.0
     */
    virtual bool ReleaseBuffer(SurfaceBuffer* buffer) = 0;

    /**
     * @brief Releases a buffer to the free queue.
     *
     *
     * @param SurfaceBuffer Indicates the pointer to the buffer to be released by producers.
     * @since 1.0
     * @version 1.0
     */
    virtual void CancelBuffer(SurfaceBuffer* buffer) = 0;

    /**
     * @brief Registers a consumer listener.
     *
     * When a buffer is placed in the dirty queue, {@link OnBufferAvailable} is called to notify consumers.
     * If the listener is repeatedly registered, only the latest one is retained.
     *
     * @param IBufferConsumerListener Indicates the listener to register.
     * @since 1.0
     * @version 1.0
     */
    virtual void RegisterConsumerListener(IBufferConsumerListener& listener) = 0;

    /**
     * @brief Unregisters the consumer listener.
     *
     * After the listener is unregistered, no callback is triggered when a buffer is placed in the dirty queue.
     *
     * @since 1.0
     * @version 1.0
     */
    virtual void UnregisterConsumerListener() = 0;
protected:
    Surface(){}
};
} // end namespace
#endif